<template>
	<view class="uni-countdown">
		<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
		<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{ dayText }}</text>
		<text v-if="showHour" :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
		<text v-if="showHour" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
		<text v-if="showMinute" :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
		<text v-if="showMinute" :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
		<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
		<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{ secondText }}</text>
	</view>
</template>
<script>
import { initVueI18n } from '@dcloudio/uni-i18n';
import messages from './i18n/index.js';
const { t } = initVueI18n(messages);
/**
 * Countdown 倒计时
 * @description 倒计时组件
 * @tutorial https://ext.dcloud.net.cn/plugin?id=25
 * @property {String} backgroundColor 背景色
 * @property {String} color 文字颜色
 * @property {Number} day 天数
 * @property {Number} hour 小时
 * @property {Number} minute 分钟
 * @property {Number} second 秒
 * @property {Number} timestamp 时间戳
 * @property {Boolean} showDay = [true|false] 是否显示天数
 * @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
 * @property {String} splitorColor 分割符号颜色
 * @event {Function} timeup 倒计时时间到触发事件
 * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
 */
export default {
	name: 'UniCountdown',
	emits: ['timeup'],
	props: {
		showDay: {
			type: Boolean,
			default: true
		},
		showHour: {
			type: Boolean,
			default: true
		},
		showMinute: {
			type: Boolean,
			default: true
		},
		showColon: {
			type: Boolean,
			default: true
		},
		start: {
			type: Boolean,
			default: true
		},
		backgroundColor: {
			type: String,
			default: ''
		},
		color: {
			type: String,
			default: '#333'
		},
		fontSize: {
			type: Number,
			default: 14
		},
		splitorColor: {
			type: String,
			default: '#333'
		},
		day: {
			type: Number,
			default: 0
		},
		hour: {
			type: Number,
			default: 0
		},
		minute: {
			type: Number,
			default: 0
		},
		second: {
			type: Number,
			default: 0
		},
		timestamp: {
			type: Number,
			default: 0
		},
		zeroPad: {
			type: Boolean,
			default: true
		}
	},
	data() {
		return {
			timer: null,
			syncFlag: false,
			d: '00',
			h: '00',
			i: '00',
			s: '00',
			leftTime: 0,
			seconds: 0
		};
	},
	computed: {
		dayText() {
			return t('uni-countdown.day');
		},
		hourText(val) {
			return t('uni-countdown.h');
		},
		minuteText(val) {
			return t('uni-countdown.m');
		},
		secondText(val) {
			return t('uni-countdown.s');
		},
		timeStyle() {
			const { color, backgroundColor, fontSize } = this;
			return {
				color,
				backgroundColor,
				fontSize: `${fontSize}px`,
				width: `${(fontSize * 22) / 14}px`, // 按字体大小为 14px 时的比例缩放
				lineHeight: `${(fontSize * 20) / 14}px`,
				borderRadius: `${(fontSize * 3) / 14}px`
			};
		},
		splitorStyle() {
			const { splitorColor, fontSize, backgroundColor } = this;
			return {
				color: splitorColor,
				fontSize: `${(fontSize * 12) / 14}px`,
				margin: backgroundColor ? `${(fontSize * 4) / 14}px` : ''
			};
		}
	},
	watch: {
		day(val) {
			this.changeFlag();
		},
		hour(val) {
			this.changeFlag();
		},
		minute(val) {
			this.changeFlag();
		},
		second(val) {
			this.changeFlag();
		},
		start: {
			immediate: true,
			handler(newVal, oldVal) {
				if (newVal) {
					this.startData();
				} else {
					if (!oldVal) return;
					clearInterval(this.timer);
				}
			}
		}
	},
	created: function (e) {
		this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second);
		this.countDown();
	},
	// #ifndef VUE3
	destroyed() {
		clearInterval(this.timer);
	},
	// #endif
	// #ifdef VUE3
	unmounted() {
		clearInterval(this.timer);
	},
	// #endif
	methods: {
		toSeconds(timestamp, day, hours, minutes, seconds) {
			if (timestamp) {
				return timestamp - parseInt(new Date().getTime() / 1000, 10);
			}
			return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds;
		},
		timeUp() {
			clearInterval(this.timer);
			this.$emit('timeup');
		},
		countDown() {
			let seconds = this.seconds;
			let [day, hour, minute, second] = [0, 0, 0, 0];
			if (seconds > 0) {
				day = Math.floor(seconds / (60 * 60 * 24));
				hour = Math.floor(seconds / (60 * 60)) - day * 24;
				minute = Math.floor(seconds / 60) - day * 24 * 60 - hour * 60;
				second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
			} else {
				this.timeUp();
			}
			day = day < 10 && this.zeroPad ? `0${day}` : day;
			hour = hour < 10 && this.zeroPad ? `0${hour}` : hour;
			minute = minute < 10 && this.zeroPad ? `0${minute}` : minute;
			second = second < 10 && this.zeroPad ? `0${second}` : second;
			this.d = day;
			this.h = hour;
			this.i = minute;
			this.s = second;
		},
		startData() {
			this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second);
			if (this.seconds <= 0) {
				this.seconds = this.toSeconds(0, 0, 0, 0, 0);
				this.countDown();
				return;
			}
			clearInterval(this.timer);
			this.countDown();
			this.timer = setInterval(() => {
				this.seconds--;
				if (this.seconds < 0) {
					this.timeUp();
					return;
				}
				this.countDown();
			}, 1000);
		},
		update() {
			this.startData();
		},
		changeFlag() {
			if (!this.syncFlag) {
				this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second);
				this.startData();
				this.syncFlag = true;
			}
		}
	}
};
</script>
<style lang="scss" scoped>
$font-size: 14px;

.uni-countdown {
	display: flex;
	flex-direction: row;
	justify-content: flex-start;
	align-items: center;

	&__splitor {
		margin: 0 2px;
		font-size: $font-size;
		color: #333;
	}

	&__number {
		border-radius: 3px;
		text-align: center;
		font-size: $font-size;
	}
}
</style>
